//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>

#define THREADAMOUNT        100

EXTERN void DzYield();

Int32 ThreadJoin01(void *pvPara)
{
    IThread         *pIThread;
    ThreadState     thdState;
    ECode           ec;

    ec = DzGetCurrentThread(&pIThread);
    assert(NOERROR == ec);

    ec = pIThread->GetState(&thdState);
    assert(NOERROR == ec);
    assert(ThreadState_Running == thdState);

    pIThread->Release();

    return NOERROR;
}

Int32 ThreadJoin02(void *pvPara)
{
    while (1) DzYield();

    return NOERROR;
}

Int32 ThreadJoin03(void *pvPara)
{
    IThread     *pIThread;
    ECode     ec;

    ec = DzCreateKernelThread(ThreadJoin02, (void *)0, 0,
                                (ThreadPriorityRank)0xFFFFEEEE, &pIThread);
    if (FAILED(ec)) {
        kprintf("Create thread failed, the ec = 0x%08x\n", ec);

        return ec;
    }

    ec = pIThread->Join((uint_t)pvPara);
    if (S_INTERRUPTED != ec) {
        kprintf("the join pvPara = 0x%08x, ec = 0x%08x\n", pvPara, ec);
    }

    ec = pIThread->Abort();
    assert(NOERROR == ec);
    pIThread->Release();

    return NOERROR;
}

EXTERN void JoinThreadReturn()
{
    IThread     *pIThread;
    ECode     ec;

    ec = DzCreateKernelThread(ThreadJoin01, (void *)0, 0,
                                (ThreadPriorityRank)0xFFFFEEEE, &pIThread);
    if (FAILED(ec)) {
        kprintf("Create thread failed, the ec = 0x%08x\n", ec);

        return;
    }

    ec = pIThread->Join(INFINITE);
    assert(NOERROR == ec);

    ec = pIThread->Join(INFINITE);
    assert(NOERROR == ec);

    pIThread->Release();

    ec = DzCreateKernelThread(ThreadJoin02, (void *)0, 0,
                                (ThreadPriorityRank)0xFFFFEEEE, &pIThread);
    if (FAILED(ec)) {
        kprintf("Create thread failed, the ec = 0x%08x\n", ec);

        return;
    }

    ec = pIThread->Join(100);
    assert(S_TIMED_OUT == ec);

    pIThread->Release();

    ec = DzCreateKernelThread(ThreadJoin03, (void *)INFINITE, 0,
                                (ThreadPriorityRank)0xFFFFEEEE, &pIThread);
    if (FAILED(ec)) {
        kprintf("Create thread failed, the ec = 0x%08x\n", ec);

        return;
    }

    ec = pIThread->Interrupt();
    assert(NOERROR == ec);

    ec = pIThread->Join(INFINITE);
    assert(NOERROR == ec);

    pIThread->Release();
}

EXTERN void JoinThreadParameter()
{
    IThread     *pIThread[THREADAMOUNT];
    uint_t      uBaseJoinTime = 0;
    uint_t      uJoinTime;
    ECode     ec;
    uint_t      i;

    do {
        uJoinTime = uBaseJoinTime + 0x10000000;

        kprintf("The join time = 0x%08x\n", uJoinTime);

        for (i = 0; i < THREADAMOUNT; i++) {
            ec = DzCreateKernelThread(ThreadJoin03, (void *)uJoinTime,
                                    0, (ThreadPriorityRank)0xFFFFEEEE, &pIThread[i]);

            if (FAILED(ec)) {
                kprintf("Create thread %d failed, the ec = 0x%08x\n", i, ec);

                return;
            }

            uJoinTime += 0x3;

            DzYield();
        }

        for (i = 0; i < THREADAMOUNT; i++) {
            ec = pIThread[i]->Interrupt();
            assert(NOERROR == ec);
        }

        for (i = 0; i < THREADAMOUNT; i++) {
            ec = pIThread[i]->Join(INFINITE);
            assert(NOERROR == ec);
            pIThread[i]->Release();
        }

        uBaseJoinTime += 0x10000000;
    } while (uBaseJoinTime <= 0xE0000000);

    uJoinTime = (uint_t)-1;

    kprintf("The join time = 0x%08x\n", uJoinTime);

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = DzCreateKernelThread(ThreadJoin03, (void *)uJoinTime,
                                0, (ThreadPriorityRank)0xFFFFEEEE, &pIThread[i]);

        if (FAILED(ec)) {
            kprintf("Create thread %d failed, the ec = 0x%08x\n", i, ec);

            return;
        }

        uJoinTime -= 0x3;

        DzYield();
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = pIThread[i]->Interrupt();
        assert(NOERROR == ec);
        pIThread[i]->Release();
    }
}
